package com.ynding;

import java.awt.*;

/**
 * @author Administrator
 */
public class ParticleTree extends java.applet.Applet implements Runnable {
    fPointTree root; //定义类fPointTree的对象root
    Image im; //定义Image类
    Graphics offscreen; //定义一个Graphics类
    Thread mainThread = null; //定义主线程
    int width = 200; //定义applet的宽度
    int height = 300; //定义applet的高度
    int iteration = 0;
    double kVY = -15, kVX = 0; //初始速度
    int kMaxIteration = 30;
    // 定义参数并赋值
    double kChanceOfBranchPoint = 0.3;
    double kScaleAtBranch = 0.7;

    //初始化程序
    @Override
    public void init() {
        resize(width, height);
        try {
            im = createImage(width, height);
            offscreen = im.getGraphics();
        } catch (Exception e) {
            offscreen = null;
        }
        root = new fPointTree((double) width / 2, height, kVX, kVY, null, null);
    }

    // 使用递归的方法，画出Applet。
    public void paintApplet(Graphics g, fPointTree current) {
        int i;
        g.setColor(Color.blue);
        if (current.left != null) {
            g.drawLine((int) current.x, (int) current.y, (int) current.left.x, (int) current.left.y);
            paintApplet(g, current.left);
        }
        if (current.right != null) {
            g.drawLine((int) current.x, (int) current.y, (int) current.right.x, (int) current.right.y);
            paintApplet(g, current.right);
        }
    }

    //更新数据
    @Override
    public void update(Graphics g) {
        paint(g);
    }

    //paint()方法
    @Override
    public void paint(Graphics g) {
        if (offscreen != null) {
            offscreen.setColor(Color.white);
            offscreen.fillRect(0, 0, width, height);
            paintApplet(offscreen, root);
            g.drawImage(im, 0, 0, this);
        } else {
            paintApplet(g, root);
        }
    }

    //启动线程
    @Override
    public void start() {
        if (mainThread == null) {
            mainThread = new Thread(this);
            mainThread.start();
        }
    }

    //停止线程
    @Override
    public void stop() {
        mainThread.stop();
        mainThread = null;
    }

    //对整个树作递归操作，当遇到树叶节点时，对该节点添加一个新节点，或者根据自动生成的随机数
//将该节点转化为一个树杈节点，并添加一个左节点和一个右节点。
    public void AddOneLevel(fPointTree current) {
        if (current.left == null && current.right == null) {
            if (Math.random() < kChanceOfBranchPoint) {
                //如果是一个树杈节点，对该点添加一个左节点和右节点，并且随机地改变该点的速度
                current.left = new fPointTree(current.x + current.vX,
                        current.y + current.vY,
                        kScaleAtBranch * (current.vX + Math.max(Math.abs(current.vX), Math.abs(current.vY)) * (Math.random() * 0.5 - 0.25)),
                        kScaleAtBranch * (current.vY + Math.max(Math.abs(current.vX), Math.abs(current.vY)) * (Math.random() * 0.5 - 0.25)),
                        null, null);
                current.right = new fPointTree(current.x + current.vX,
                        current.y + current.vY,
                        kScaleAtBranch * (current.vX + Math.max(Math.abs(current.vX), Math.abs(current.vY)) * (Math.random() * 0.5 - 0.25)),
                        kScaleAtBranch * (current.vY + Math.max(Math.abs(current.vX), Math.abs(current.vY)) * (Math.random() * 0.5 - 0.25)),
                        null, null);
            } else {
                //如果不是一个树杈节点，只增加一个新的左节点，不改变该点的速度
                current.left = new fPointTree(current.x + current.vX,
                        current.y + current.vY,
                        current.vX + Math.max(Math.abs(current.vX), Math.abs(current.vY)) * (Math.random() * 0.5 - 0.25),
                        current.vY + Math.max(Math.abs(current.vX), Math.abs(current.vY)) * (Math.random() * 0.5 - 0.25),
                        null, null);
            }
        } else {
            // 如果不在叶子节点上，对整个树继续作递归操作。
            if (current.left != null) {
                AddOneLevel(current.left);
            }
            if (current.right != null) {
                AddOneLevel(current.right);
            }
        }
    }

    //运行
    public void run() {
        while (mainThread != null) {
            try {
                mainThread.sleep(200);
            } catch (InterruptedException e) {
            }
            if (iteration < kMaxIteration) {
                repaint();
                AddOneLevel(root);
            } else if (iteration > 1.5 * kMaxIteration) {
                iteration = 0;
                root = new fPointTree((double) width / 2, height, kVX, kVY, null, null);
                repaint();
                AddOneLevel(root);
            }
            iteration++;

        }
        mainThread = null;
    }
}
